<?php
/**
 * AutoCurd.php
 * Created by PhpStorm.
 * User: 江小波
 * Date: 2019/6/24
 * Time: 10:39
 */

namespace app\console\command;

use app\api\util\Hump;
use app\console\command\auto_curd\tpl\AbstractController;
use app\console\command\auto_curd\tpl\CreateView;
use app\console\command\auto_curd\tpl\Model;
use app\console\command\auto_curd\tpl\ReadView;
use app\console\command\auto_curd\tpl\UpdateView;
use think\console\input\Option;
use think\Db;

class AutoCurd extends Base
{
    protected function getCmdName()
    {
        return 'auto_curd';
    }

    protected function getCmdDescription()
    {
        return 'auto_curd cmd';
    }

    protected function processResult($result)
    {
        return $result;
    }

    protected function applyOption()
    {
        $this->addOption('dir', null, Option::VALUE_REQUIRED, 'dir');
        // 添加可配置参数，不传则为null
        $this->addOption('database', null, Option::VALUE_OPTIONAL, 'database');
    }

    /**
     * 命令行执行
     */
    // php cmd auto_curd --action generate --dir common/auto_curd/ --database php_system
    public function generate($params, $options)
    {
        if (empty($options['database'])) {
            $databaseName = config('database.database');
        } else {
            $databaseName = $options['database'];
        }
        $dir = $options['dir'];
        // 获取表名称、表注释
        $tables = Db::query($this->getSqlByTable($databaseName));
        // 迭代数据表
        foreach ($tables as &$table) {
            $columns = Db::query($this->getSqlByColumn($table['table_name'], $databaseName));
            // 生成对应的数据库表的 ORM
            $this->generateORM($columns, $dir, $table, $databaseName);
            // 生成对应的视图文件
            $this->generateCreateView($columns, $dir, $table, $databaseName);
            $this->generateUpdateView($columns, $dir, $table, $databaseName);
            $this->generateReadView($columns, $dir, $table, $databaseName);
            $this->generateDeleteView($columns, $dir, $table, $databaseName);
            // 生成对应的控制抽象类
            $this->generateAbstractController($columns, $dir, $table, $databaseName);
        }
    }

    /**
     * 获取表名称、表注释
     * @param $databaseName
     * @return string
     */
    private function getSqlByTable($databaseName)
    {
        return "SELECT `table_name`,`table_comment` FROM `information_schema`.`tables` WHERE `table_schema` = '{$databaseName}'";
    }

    /**
     * 获取列名称、列注释、默认值、数据类型、字符最大长度、列键、能否为NULL、数值精度、额外、顺序位置、列键
     * @param $tableName
     * @param $databaseName
     * @return string
     */
    private function getSqlByColumn($tableName, $databaseName)
    {
        $field = "`column_name`,`column_comment`,`column_default`,`data_type`,`character_maximum_length`,`column_key`,`is_nullable`,`numeric_precision`,`extra`,`ordinal_position`,`column_type`";
        return "SELECT {$field} FROM `information_schema`.`columns` WHERE `table_schema` = '{$databaseName}' AND `table_name` = '{$tableName}'";
    }

    /**
     * 生成对应的数据库表的 ORM
     * @param $dir
     * @param $table
     * @param $databaseName
     */
    private function generateORM(&$columns, $dir, $table, $databaseName)
    {
        $className = Hump::camel($table['table_name']) . 'Model';
        // 文件内容
        $tpl = Model::begin($dir, $className, $databaseName);
        $construct = "";
        $PRI_NAME = "id";
        foreach ($columns as &$column) {
            $tpl .= Model::content($column);
            $construct .= Model::construct($column);
            if ($column['column_key'] === 'PRI') {
                $PRI_NAME = $column['column_name'];
            }
        }
        $tpl .= Model::end($construct, $table['table_name'],$PRI_NAME);
        // 生成文件
        $tDir = APP_PATH . $dir . $databaseName . '/model/';
        if (!is_dir($tDir)) {
            @mkdir($tDir, 755, true);
        }
        $filename = $tDir . "{$className}.php";
        @file_put_contents($filename, $tpl);
    }

    /**
     * 添加操作模板
     * @param $columns
     * @param $dir
     * @param $table
     * @param $databaseName
     */
    private function generateCreateView(&$columns, $dir, $table, $databaseName)
    {
        // 文件内容
        $tpl = CreateView::begin($table['table_name']);
        foreach ($columns as &$column) {
            $tpl .= CreateView::content($column);
        }
        $tpl .= CreateView::end();
        // 生成文件
        $tDir = APP_PATH . $dir . $databaseName . '/view/' . $table['table_name'] . '/';
        if (!is_dir($tDir)) {
            @mkdir($tDir, 755, true);
        }
        $filename = $tDir . "create.html";
        @file_put_contents($filename, $tpl);
    }

    /**
     * 修改操作模板
     * @param $columns
     * @param $dir
     * @param $table
     * @param $databaseName
     */
    private function generateUpdateView(&$columns, $dir, $table, $databaseName)
    {
        // 文件内容
        $tpl = UpdateView::begin($table['table_name']);
        foreach ($columns as &$column) {
            $tpl .= UpdateView::content($column);
        }
        $tpl .= UpdateView::end();
        // 生成文件
        $tDir = APP_PATH . $dir . $databaseName . '/view/' . $table['table_name'] . '/';
        if (!is_dir($tDir)) {
            @mkdir($tDir, 755, true);
        }
        $filename = $tDir . "update.html";
        @file_put_contents($filename, $tpl);
    }

    /**
     * 读取操作模板
     * @param $columns
     * @param $dir
     * @param $table
     * @param $databaseName
     */
    private function generateReadView(&$columns, $dir, $table, $databaseName)
    {
        $th = $td = "";
        $PRI_NAME = "id";
        foreach ($columns as &$column) {
            $th .= ReadView::thead($column);
            $td .= ReadView::content($column);
            if ($column['column_key'] === 'PRI') {
                $PRI_NAME = $column['column_name'];
            }
        }
        // 文件内容
        $tpl = ReadView::begin($table, $th, $td, $PRI_NAME);
        $tpl .= ReadView::end();
        // 生成文件
        $tDir = APP_PATH . $dir . $databaseName . '/view/' . $table['table_name'] . '/';
        if (!is_dir($tDir)) {
            @mkdir($tDir, 755, true);
        }
        $filename = $tDir . "read.html";
        @file_put_contents($filename, $tpl);
    }

    /**
     * 删除操作模板
     * @param $columns
     * @param $dir
     * @param $table
     * @param $databaseName
     */
    private function generateDeleteView(&$columns, $dir, $table, $databaseName)
    {

    }

    private function generateAbstractController(&$columns, $dir, $table, $databaseName)
    {
        $baseName = Hump::camel($table['table_name']);
        $create = $update = $read = $delete = "";
        $PRI_NAME = "id";
        foreach ($columns as &$column) {
            $create .= AbstractController::create($column);
            $update .= AbstractController::update($column);
            if ($column['column_key'] === 'PRI') {
                $PRI_NAME = $column['column_name'];
            }
        }
        $read = AbstractController::read($baseName,$table['table_name'],$databaseName);
        $delete = AbstractController::delete($baseName,$PRI_NAME);
        // 文件内容
        $tpl = AbstractController::begin($dir, $baseName, $databaseName);
        $tpl .= AbstractController::content($create, $update, $read, $delete,$baseName,$table['table_name'],$databaseName,$PRI_NAME);
        $tpl .= AbstractController::end();
        // 生成文件
        $tDir = APP_PATH . $dir . $databaseName . '/controller/';
        if (!is_dir($tDir)) {
            @mkdir($tDir, 755, true);
        }
        $filename = $tDir . "{$baseName}Controller.php";
        @file_put_contents($filename, $tpl);
    }
}